package com.kacheap.configuration;

import java.util.EnumSet;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.StateMachineContext;
import org.springframework.statemachine.StateMachinePersist;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import org.springframework.statemachine.persist.DefaultStateMachinePersister;
import org.springframework.statemachine.support.DefaultStateMachineContext;

import com.kacheap.data.enums.OrderStatus;
import com.kacheap.data.enums.OrderStatusChangeEvent;
import com.kacheap.data.pojo.Order;

@Configuration
@EnableStateMachine(name = "orderStateMachine")
public class OrderStateMachineConfig extends StateMachineConfigurerAdapter<OrderStatus, OrderStatusChangeEvent> {
 
    /**
     * 配置状态
     * @param states
     * @throws Exception
     */
    public void configure(StateMachineStateConfigurer<OrderStatus, OrderStatusChangeEvent> states) throws Exception {
        states
                .withStates()
                .initial(OrderStatus.WAIT_PAYMENT)
                .states(EnumSet.allOf(OrderStatus.class));
    }
 
    /**
	 * 配置状态转换事件关系
	 * 
	 * @param transitions
	 * @throws Exception
	 */
    public void configure(StateMachineTransitionConfigurer<OrderStatus, OrderStatusChangeEvent> transitions) throws Exception {
        transitions
                .withExternal().event(OrderStatusChangeEvent.PAYED).source(OrderStatus.WAIT_PAYMENT).target(OrderStatus.WAIT_DELIVER)
                .and()
                .withExternal().event(OrderStatusChangeEvent.DELIVERY).source(OrderStatus.WAIT_DELIVER).target(OrderStatus.WAIT_RECEIVE)
                .and()
                .withExternal().event(OrderStatusChangeEvent.RECEIVED).source(OrderStatus.WAIT_RECEIVE).target(OrderStatus.FINISH)
                .and()
                .withExternal().event(OrderStatusChangeEvent.REFUND).source(OrderStatus.FINISH).target(OrderStatus.WAIT_DELIVER);
    }
 
    /**
     * 持久化配置
     * 实际使用中，可以配合redis等，进行持久化操作
     * @return
     */
    @Bean
	public DefaultStateMachinePersister<OrderStatus, OrderStatusChangeEvent, Order> persister() {
        return new DefaultStateMachinePersister<>(new StateMachinePersist<OrderStatus, OrderStatusChangeEvent, Order>() {

			@Override
			public void write(StateMachineContext<OrderStatus, OrderStatusChangeEvent> context, Order order) throws Exception {
				System.err.println("DefaultStateMachinePersister ==> write : " + order.getId());
			}

			@Override
			public StateMachineContext<OrderStatus, OrderStatusChangeEvent> read(Order order) throws Exception {
				return new DefaultStateMachineContext<OrderStatus, OrderStatusChangeEvent>(order.getStatus(), null, null, null);
			}
			
        });
    }
}